package com.sdwl.brcl.validation.validation;

import cn.hutool.core.util.ObjectUtil;
import com.sdwl.brcl.validation.enums.EnumAware;
import com.sdwl.brcl.validation.enums.MoonValidationEnum;
import com.sdwl.brcl.validation.exception.ValidationException;
import com.sdwl.brcl.view.ServerResponse;
import org.apache.commons.lang3.ArrayUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * @author xied
 * @date 2021年06月11日 14:08
 */
public class Verifier {
    private List<ValidatorElement> validatorElements = new ArrayList();

    public Verifier() {
    }

    public static Verifier init() {
        return new Verifier();
    }

    public Verifier notNull(Object value, String name) {
        ValidatorElement validatorElement = new ValidatorElement(value, name, new NotNullValidator());
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier notNull(Object value, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(value, enumAware, new NotNullValidator());
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier notEmpty(Object value, String name) {
        ValidatorElement validatorElement = new ValidatorElement(value, name, new NotEmptyValidator());
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier notEmpty(Object value, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(value, enumAware, new NotEmptyValidator());
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier notBlank(String value, String name) {
        ValidatorElement validatorElement = new ValidatorElement(value, name, new StringValidator(0));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier notBlank(String value, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(value, enumAware, new StringValidator(0));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier minLength(String value, int minLength, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, minLength}, name, new StringValidator(4));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier minLength(String value, int minLength, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, minLength}, enumAware, new StringValidator(4));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier maxLength(String value, int maxLength, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, maxLength}, name, new StringValidator(5));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier maxLength(String value, int maxLength, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, maxLength}, enumAware, new StringValidator(5));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier minArrayLength(Object value, int minLength, String name) {
        int length = ArrayUtils.getLength(value);
        this.gtEq(length, minLength, name);
        return this;
    }

    public Verifier minArrayLength(Object value, int minLength, EnumAware enumAware) {
        int length = ArrayUtils.getLength(value);
        this.gtEq(length, minLength, enumAware);
        return this;
    }

    public Verifier maxArrayLength(Object value, int maxLength, String name) {
        int length = ArrayUtils.getLength(value);
        this.ltEq(length, maxLength, name);
        return this;
    }

    public Verifier maxArrayLength(Object value, int maxLength, EnumAware enumAware) {
        int length = ArrayUtils.getLength(value);
        this.ltEq(length, maxLength, enumAware);
        return this;
    }

    public Verifier eqLength(String value, int maxLength, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, maxLength}, name, new StringValidator(6));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier eqLength(String value, int maxLength, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, maxLength}, enumAware, new StringValidator(6));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustEmpty(Collection<?> value, String name) {
        ValidatorElement validatorElement = new ValidatorElement(value, name, new CollectionValidator(0));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustEmpty(Collection<?> value, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(value, enumAware, new CollectionValidator(0));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustFalse(Boolean bool, String name) {
        ValidatorElement validatorElement = new ValidatorElement(bool, name, new BooleanValidator(0));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustFalse(Boolean bool, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(bool, enumAware, new BooleanValidator(0));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier inEnums(String value, EnumAware[] enumAwares, String name) {
        ValidatorElement validatorElement = new ValidatorElement(value, name, new EnumAwareValidator(enumAwares, 1));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier inEnums(String value, EnumAware[] enumAwares, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(value, enumAware, new EnumAwareValidator(enumAwares, 1));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier notInEnums(String value, EnumAware[] enumAwares, String name) {
        ValidatorElement validatorElement = new ValidatorElement(value, name, new EnumAwareValidator(enumAwares, 2));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier notInEnums(String value, EnumAware[] enumAwares, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(value, enumAware, new EnumAwareValidator(enumAwares, 2));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustTrue(Boolean bool, String name) {
        ValidatorElement validatorElement = new ValidatorElement(bool, name, new BooleanValidator(1));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustTrue(Boolean bool, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(bool, enumAware, new BooleanValidator(1));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier minSize(Collection<?> value, int minSize, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, minSize}, name, new CollectionValidator(1));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier minSize(Collection<?> value, int minSize, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, minSize}, enumAware, new CollectionValidator(1));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier maxSize(Collection<?> value, int maxSize, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, maxSize}, name, new CollectionValidator(2));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier maxSize(Collection<?> value, int maxSize, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, maxSize}, enumAware, new CollectionValidator(2));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier eqSize(Collection<?> value, int eqSize, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, eqSize}, name, new CollectionValidator(3));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier eqSize(Collection<?> value, int eqSize, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, eqSize}, enumAware, new CollectionValidator(3));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier gtThan(int value, int expectVal, String name) {
        this.gtThan((long) value, (long) expectVal, name);
        return this;
    }

    public Verifier gtThan(int value, int expectVal, EnumAware enumAware) {
        this.gtThan((long) value, (long) expectVal, enumAware);
        return this;
    }

    public Verifier gtEq(int value, int expectVal, String name) {
        this.gtEq((long) value, (long) expectVal, name);
        return this;
    }

    public Verifier gtEq(int value, int expectVal, EnumAware enumAware) {
        this.gtEq((long) value, (long) expectVal, enumAware);
        return this;
    }

    public Verifier ltThan(int value, int expectVal, String name) {
        this.ltThan((long) value, (long) expectVal, name);
        return this;
    }

    public Verifier ltThan(int value, int expectVal, EnumAware enumAware) {
        this.ltThan((long) value, (long) expectVal, enumAware);
        return this;
    }

    public Verifier ltEq(int value, int expectVal, String name) {
        this.ltEq((long) value, (long) expectVal, name);
        return this;
    }

    public Verifier ltEq(int value, int expectVal, EnumAware enumAware) {
        this.ltEq((long) value, (long) expectVal, enumAware);
        return this;
    }

    public Verifier mustEq(int value, int expectVal, String name) {
        this.mustEq((long) value, (long) expectVal, name);
        return this;
    }

    public Verifier mustEq(int value, int expectVal, EnumAware enumAware) {
        this.mustEq((long) value, (long) expectVal, enumAware);
        return this;
    }

    public Verifier mustEq(String value, String expectVal, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, name, new StringValidator(2));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustEq(String value, String expectVal, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, enumAware, new StringValidator(2));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier notEq(String value, String expectVal, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, name, new StringValidator(7));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier notEq(String value, String expectVal, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, enumAware, new StringValidator(7));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustEqIgnoreCase(String value, String expectVal, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, name, new StringValidator(3));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustEqIgnoreCase(String value, String expectVal, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, enumAware, new StringValidator(3));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier gtThan(long value, long expectVal, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, name, new NumberValidator(0));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier gtThan(long value, long expectVal, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, enumAware, new NumberValidator(0));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier gtEq(long value, long expectVal, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, name, new NumberValidator(2));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier gtEq(long value, long expectVal, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, enumAware, new NumberValidator(2));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier ltThan(long value, long expectVal, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, name, new NumberValidator(1));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier ltThan(long value, long expectVal, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, enumAware, new NumberValidator(1));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier ltEq(long value, long expectVal, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, name, new NumberValidator(3));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier ltEq(long value, long expectVal, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, enumAware, new NumberValidator(3));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustEq(long value, long expectVal, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, name, new NumberValidator(4));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier mustEq(long value, long expectVal, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new Object[]{value, expectVal}, enumAware, new NumberValidator(4));
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier regex(String value, String regex, String name) {
        ValidatorElement validatorElement = new ValidatorElement(new String[]{value, regex}, name, new RegexValidator());
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier regex(String value, String regex, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(new String[]{value, regex}, enumAware, new RegexValidator());
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier eachNotNull(Collection<?> collection, String name) {
        ValidatorElement validatorElement = new ValidatorElement(collection, name, new CollectionEachNotNullValidator());
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier eachNotNull(Collection<?> collection, EnumAware enumAware) {
        ValidatorElement validatorElement = new ValidatorElement(collection, enumAware, new CollectionEachNotNullValidator());
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier on(Object value, String name, Validator validator) {
        ValidatorElement validatorElement = new ValidatorElement(value, name, validator);
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier on(Object value, EnumAware enumAware, Validator validator) {
        ValidatorElement validatorElement = new ValidatorElement(value, enumAware, validator);
        this.validatorElements.add(validatorElement);
        return this;
    }

    public Verifier with(boolean b) {
        if (!b) {
            this.removeLastValidationElement();
        }

        return this;
    }

    public Verifier errorCode(String errorCode) {
        this.getLastValidationElement().setErrorCode(errorCode);
        return this;
    }

    public Verifier errorMsg(String errorMsg) {
        this.getLastValidationElement().setErrorMsg(errorMsg);
        return this;
    }

    public Verifier error(EnumAware enumAware) {
        ValidatorElement lastValidationElement = this.getLastValidationElement();
        lastValidationElement.setErrorCode(enumAware.getCode());
        lastValidationElement.setErrorMsg(enumAware.getName());
        return this;
    }

    public Verifier validate() {
        this.result(true);
        return this;
    }

    public ServerResponse result() {
        return this.result(false);
    }

    private ServerResponse result(boolean invalidFast) {
        ServerResponse backMessage = new ServerResponse();
        ValidationResult result = new ValidationResult();
        Iterator var3 = this.validatorElements.iterator();
        while (var3.hasNext()) {
            ValidatorElement validatorElement = (ValidatorElement) var3.next();
            boolean validate = validatorElement.getValidator().validate(validatorElement.getValidateValue());
            if (!validate) {
                String errorCode = validatorElement.getErrorCode();
                String errorMsg = validatorElement.getErrorMsg();
                if (invalidFast) {
                    throw new ValidationException(errorCode, errorMsg);
                }
                ValidationError validationError = new ValidationError();
                validationError.setErrorCode(errorCode).setErrorMsg(errorMsg).setName(validatorElement.getValidateName()).setInvalidValue(validatorElement.getValidateValue());
                backMessage.setStatus(-1);
                result.addMsg(errorMsg);
                result.addErrorStringCode(validationError);
            }
        }
        this.validatorElements.clear();
        if (ObjectUtil.isNotNull(result.getMsgList()) && ObjectUtil.isNotNull(result.getErrorStringCodeList())) {
            backMessage.setMsg(result.getMsgList().toString());
            backMessage.setData(result.getErrorStringCodeList());
            return backMessage;
        }
        return ServerResponse.createBySuccess();
    }

    private ValidatorElement getLastValidationElement() {
        if (this.validatorElements.isEmpty()) {
            throw new ValidationException(MoonValidationEnum.VALIDATION_ELEMENT_NOT_NULL);
        } else {
            return (ValidatorElement) this.validatorElements.get(this.validatorElements.size() - 1);
        }
    }

    private ValidatorElement removeLastValidationElement() {
        if (this.validatorElements.isEmpty()) {
            throw new ValidationException(MoonValidationEnum.VALIDATION_ELEMENT_NOT_NULL);
        } else {
            return (ValidatorElement) this.validatorElements.remove(this.validatorElements.size() - 1);
        }
    }
}
